<?php

namespace iBrand\Shop\Server\Service;

use iBrand\Component\Order\Repositories\OrderRepository;
use iBrand\Shop\Core\Models\Order;
use iBrand\Component\Discount\Services\DiscountService;
use iBrand\TNF\Core\Models\Staff;
use iBrand\Component\Order\Models\OrderItem;
use iBrand\Component\Product\Models\Product;
use iBrand\Component\Product\Models\Goods;
use iBrand\Component\Order\Processor\OrderProcessor;
use iBrand\Component\Point\Repository\PointRepository;

class OrderService
{

    protected $discountService;
    protected $orderProcessor;
    protected $pointRepository;
    protected $orderRepository;

    public function __construct(DiscountService $discountService,
                                OrderProcessor $orderProcessor,
                                PointRepository $pointRepository,
                                OrderRepository $orderRepository)
    {
        $this->discountService = $discountService;
        $this->orderProcessor = $orderProcessor;
        $this->pointRepository = $pointRepository;
        $this->orderRepository = $orderRepository;
    }

    /**
     * * 生成订单对象
     *
     * @param $cartItems
     * @param $user_id
     * @param $shop_id
     *
     * @return array
     */
    public function createOrder($cartItems, $user_id, $shop_id)
    {
        $order = new Order([
            'user_id' => $user_id,
            'channel' => 'shop',
            'channel_id' => $shop_id,
        ]);
        $order->order_no = build_order_no('ST');
        if (request('type') AND request('type') == 'employee') {
            if ($user = request()->user('api') AND $userRole = $user->roles->first() AND
                $userRole->name == 'employee' AND
                $staff = Staff::where('mobile', $user->mobile)->first() AND
                $staff->active_status == 1
            ) {
                $ruleGoods = $this->discountService->getGoodsByRole($userRole->name)['spu'];
                foreach ($cartItems as $key => $item) {
                    if (!in_array($item->model->detail_id, $ruleGoods)) {
                        return ['order' => [], 'status' => false, 'code' => 500, 'message' => '非法请求，包含非内购商品'];
                    }
                }
            } else {
                return ['order' => [], 'status' => false, 'code' => 500, 'message' => '非法请求，无权限进行此内购'];
            }
            $order->order_no = build_order_no('NG');
            $order->type = Order::TYPE_IN_SOURCE;
        }

        //门店O2O订单
        $order->type = Order::TYPE_SHOP;
        //2. 生成临时订单对象
        foreach ($cartItems as $key => $item) {
            if ($item->qty > 0) {
                $item_meta = [
                    'image' => $item->img,
                    'detail_id' => $item->model->detail_id,
                ];

                if (isset($item->dynamic_sku['id'])) {
                    $item_meta['dynamic_sku'] = $item->dynamic_sku;
                } else {
                    $item_meta['specs_text'] = $item->model->specs_text;
                }
                $singleDiscount = $this->discountService->getSingleDiscountByGoods($item->model);
                $orderItem = new OrderItem([
                    'quantity' => $item->qty,
                    'unit_price' => $this->discountService->getProductPriceFromSingleDiscount($item->model, $singleDiscount),
                    'item_id' => $item->id,
                    'type' => $item->__model,
                    'item_name' => $item->name,
                    'item_meta' => $item_meta,
                ]);

                if ($order->type == Order::TYPE_IN_SOURCE) { //内购的话设置为商品吊牌价
                    $orderItem->unit_price = $item->model->market_price;
                }

                if ($order->type == Order::TYPE_SUIT) { //套餐的话设置为商品套餐价
                    $orderItem->unit_price = $item->price;
                    $orderItem->unit_price = $item->price * $item->qty;
                }

                $orderItem->recalculateUnitsTotal();
                $order->addItem($orderItem);
            }
        }

        if ($goods_id = request('goods_id')) {
            $quantity = request('qty') ? request('qty') : 1;
            if ($quantity > 0) {
                if (request('goods_type') AND request('goods_type') == 'sku') {
                    $product = Product::find($goods_id);
                    $orderItem = new OrderItem([
                        'quantity' => $quantity,
                        'unit_price' => $product->sell_price,
                        'item_id' => $product->id,
                        'type' => Product::class,
                        'item_name' => $product->name,
                        'item_meta' => [
                            'image' => $product->photo_url,
                            'detail_id' => $product->detail_id,
                        ]]);
                } else {
                    $goods = Goods::find($goods_id);
                    $orderItem = new OrderItem([
                        'quantity' => $quantity,
                        'unit_price' => $goods->sell_price,
                        'item_id' => $goods->id,
                        'type' => Goods::class,
                        'item_name' => $goods->name,
                        'item_meta' => [
                            'image' => $goods->photo_url,
                            'detail_id' => $goods->detail_id,
                        ]]);
                }

                $orderItem->recalculateUnitsTotal();
                $order->addItem($orderItem);
            }
        }

        $order = $this->orderProcessor->create($order);
        if (!$order) {

            return ['order' => [], 'status' => false, 'code' => 500, 'message' => '订单提交失败，请确认后重试'];
        }

        return ['order' => $order, 'status' => true, 'code' => 200, 'message' => ''];
    }

    /**
     * 获取订单积分信息
     *
     * @param $order
     *
     * @return array
     */
    public function getOrderPoint($order)
    {
        $orderPoint = [];
        if (settings('point_enabled') AND settings('point_proportion')) {
            $total = $this->getCanUsePointSum($order);

            $userPoint = $this->pointRepository->getSumPointValid(request('user_id'), 'default');
            $userPoint = $userPoint ? number_format($userPoint, 2, ".", "") : 0;
            $pointToMoney = settings('point_proportion') ? settings('point_proportion') : 0;
            $pointLimit = (settings('point_order_limit') ? settings('point_order_limit') : 1) / 100;
            $pointAmount = min($userPoint * $pointToMoney, $total * $pointLimit);
            $orderPoint = [
                'userPoint' => $userPoint,
                'pointToMoney' => $pointToMoney,
                'pointLimit' => $pointLimit,
                'pointAmount' => -$pointAmount,
                'pointCanUse' => $pointAmount / $pointToMoney ? number_format($pointAmount / $pointToMoney, 2, ".", "") : 0,
                'pointCanotUseAmount' => $this->getCanUsePointSum($order, false)
            ];
        }

        if ($order->type == Order::TYPE_SUIT && !settings('point_suit_enabled')) {
            $orderPoint = [];
        }

        return $orderPoint;
    }

    /**
     * 获取能使用\不能使用积分抵扣的金额
     * @param $order
     * @param $type
     * @return mixed
     */
    private function getCanUsePointSum($order, $type = true)
    {
        $items = $order->items;
        $filters = $items->filter(function ($item, $key) use ($type) {
            $goods = Goods::find($item->getItemId());
            if ($type) {
                return $goods->hasOnePoint->can_use_point;
            } else {
                return !$goods->hasOnePoint->can_use_point;
            }
        });
        return $filters->sum('total');
    }

    /**
     * 获取订单优惠信息
     *
     * @param $order
     *
     * @return array
     */
    public function getDiscount($order)
    {
        //3.get available discounts
        $discounts = $this->discountService->getEligibilityDiscounts($order, 'shop');
        $in_source_discount_id = false;
        if ($discounts) {
            $discounts = $discounts->filter(function ($item) use ($order, &$in_source_discount_id) {
                if ($order->type == Order::TYPE_IN_SOURCE) {
                    $flag = false;
                    foreach ($item->rules as $rule) {
                        if ($rule->type == 'contains_role' AND $rule->getRoleName() == 'employee') {
                            $flag = true;
                            $in_source_discount_id = $item->id;
                        }
                    }

                    return $flag;
                } else {
                    foreach ($item->rules as $rule) {
                        if ($rule->type == 'contains_role' AND $rule->getRoleName() == 'employee') {
                            return false;
                        }
                    }

                    return true;
                }
            });

            //修复过滤后discount为0时非false 的问题。
            if (count($discounts) == 0) {
                $discounts = false;
            } else {
                $discounts_ = [];
                foreach ($discounts as $discount) {
                    $discounts_[] = $discount;
                }
                $discounts = $discounts_;
            }
        }

        $user = request()->user();
        $coupons = $this->discountService->getEligibilityCoupons($order, $user->id, 'shop');
        if ($coupons AND $coupons->where('discount.code', 'vipeaknewonline')->first()) {
            $isRemoveCoupon = false;
            foreach ($order->getItems() as $item) {
                $sku = $item->getItemKey();
                if ($condition = SingleDiscountCondition::where('name', $sku)->whereHas('discount', function ($query) {
                    return $query->where('status', 1)
                        ->where('ends_at', '>', Carbon::now());
                })->first()
                ) {
                    $isRemoveCoupon = true;
                }
            }

            if ($isRemoveCoupon) {
                $coupons = $coupons->filter(function ($item) {
                    return $item->discount->code != 'vipeaknewonline';
                });
            }
        }

        if ($coupons AND $order->type != Order::TYPE_IN_SOURCE) {
            $coupons_ = [];
            foreach ($coupons as $coupon) {
                $coupons_[] = $coupon;
            }

            $coupons = $coupons_;
        } else {
            $coupons = [];
        }

        if ($order->type == Order::TYPE_SUIT) {
            //如果是套餐订单不能使用促销活动和优惠券。
            $discounts = [];
            $coupons = [];
        }

        return ['discounts' => $discounts, 'in_source_discount_id' => $in_source_discount_id, 'coupons' => $coupons];
    }

    /**
     * 取消订单
     * @return mixed
     */
    public function cancel($order)
    {
        $this->orderProcessor->cancel($order);

        //TODO: 用户未付款前取消订单后，需要还原库存
        foreach ($order->getItems() as $item) {
            $model = $item->type;
            $model = new $model();
            $product = $model->find($item->item_id);
            /*$product->restoreO2oStock($item->quantity, $order->channel_id);
            $product->restoreO2oSales($item->quantity, $order->channel_id);*/
            $o2oProduct = $product->getO2oProduct($order->channel_id);
            $o2oProduct->restoreStock($item->quantity);
            $o2oProduct->restoreSales($item->quantity);
        }

        return $this->api([], true, 200, '订单取消成功');
    }
}